﻿// client for Movie Review RESTful web service

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using MovieReview.Models;

namespace MovieReviewsClient
{
    public class Program
    {
        // RunAsync awaits results from async methods so must be async itself
        public static async Task RunAsync()                         // async methods return Task or Task<T>
        {
            try
            {
                using (HttpClient client = new HttpClient())                                            // Dispose() called autmatically in finally block
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));            // or application/xml

                    HttpResponseMessage response = await client.GetAsync("api/movie");                  // async call, await suspends until task finished            
                    if (response.IsSuccessStatusCode)                                                   // 200.299
                    {
                        // read result 
                        var listings = await response.Content.ReadAsAsync<IEnumerable<MovieReview.Models.MovieListing>>();
                        foreach (var listing in listings)
                        {
                            Console.WriteLine(listing.MovieName + "\t " + listing.Rating + "\t " + listing.ReleaseDate + "\t " + listing.Review + "\t " + listing.Reviewer);
                        }
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        // Get listings by name of movie
        static async Task GetByNameAsync(String movie)                         // async methods return Task or Task<T>
        {
            try
            {
                using (HttpClient client = new HttpClient())                                            // Dispose() called autmatically in finally block
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));            // or application/xml
                    string url = "api/movie/" + movie;
                    HttpResponseMessage response = await client.GetAsync(url);                  // async call, await suspends until task finished            
                    if (response.IsSuccessStatusCode)                                                   // 200.299
                    {
                        // read result 
                        var listings = await response.Content.ReadAsAsync<IEnumerable<MovieReview.Models.MovieListing>>();
                        foreach (var listing in listings)
                        {
                            Console.WriteLine(listing.MovieName + "\t " + listing.Rating + "\t " + listing.ReleaseDate + "\t " + listing.Review + "\t " + listing.Reviewer);
                        }
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        
        // Delete movie listing by a user
        static async Task DeleteAsync(String movie, String user)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");
                    string url = "api/movie/" + movie + "/" + user;
                    // de-list Inception
                    // Delete/api/Inception                                                    
                    HttpResponseMessage response = await client.DeleteAsync(url);

                    if (!response.IsSuccessStatusCode)
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);  
                    }  
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }     
        }

        // Add a movie listing
        static async Task AddAsync(MovieListing newListing)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON - preference for response 
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    // POST /api/movie with a listing serialised in request body
                    
                    HttpResponseMessage response = await client.PostAsJsonAsync("api/movie", newListing);   // or PostAsXmlAsync
                    if (response.IsSuccessStatusCode)                                                       // 200 .. 299
                    {
                        Uri newStockUri = response.Headers.Location;
                        var listing = await response.Content.ReadAsAsync<MovieListing>();
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        // Update a movie listing
        static async Task UpdateAsync(MovieListing listing)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");
                    String url = "api/movie/" + listing.MovieName + "/" + listing.Reviewer;

                    // update by Put to api/movie/Inception a listing serialised in request body
                    HttpResponseMessage response = await client.PutAsJsonAsync(url, listing);
     
                    if (!response.IsSuccessStatusCode)
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        // Get listings with a rating higher than double given
        static async Task GetByRatingAsync(double rating)                         // async methods return Task or Task<T>
        {
            try
            {
                using (HttpClient client = new HttpClient())                                            // Dispose() called autmatically in finally block
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));            // or application/xml
                    string url = "api/movie?rating=" + rating;
                    HttpResponseMessage response = await client.GetAsync(url);                  // async call, await suspends until task finished            
                    if (response.IsSuccessStatusCode)                                                   // 200.299
                    {
                        // read result 
                        var listings = await response.Content.ReadAsAsync<IEnumerable<MovieReview.Models.MovieListing>>();
                        foreach (var listing in listings)
                        {
                            Console.WriteLine(listing.MovieName + "\t  " + listing.Rating + "\t  " + listing.ReleaseDate + "\t  " + listing.Review + "\t " + listing.Reviewer);          
                        }
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        // Get listings with a release date on or after date given
        static async Task GetByReleaseDateAsync(DateTime date)                         // async methods return Task or Task<T>
        {
            try
            {
                using (HttpClient client = new HttpClient())                                            // Dispose() called autmatically in finally block
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));            // or application/xml
                    string url = "api/movie?date=" + date.ToShortDateString();
                    HttpResponseMessage response = await client.GetAsync(url);                  // async call, await suspends until task finished            
                    if (response.IsSuccessStatusCode)                                                   // 200.299
                    {
                        // read result 
                        var listings = await response.Content.ReadAsAsync<IEnumerable<MovieReview.Models.MovieListing>>();
                        foreach (var listing in listings)
                        {
                            Console.WriteLine(listing.MovieName + "\t " + listing.Rating + "\t " + listing.ReleaseDate + "\t " + listing.Review + "\t " + listing.Reviewer);         
                        }
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }

                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            
        }

        // Get listings by user
        static async Task GetByUserAsync(String user)                         // async methods return Task or Task<T>
        {
            try
            {
                using (HttpClient client = new HttpClient())                                            // Dispose() called autmatically in finally block
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));            // or application/xml
                    string url = "api/movie?user=" + user;
                    HttpResponseMessage response = await client.GetAsync(url);                  // async call, await suspends until task finished            
                    if (response.IsSuccessStatusCode)                                                   // 200.299
                    {
                        // read result 
                        var listings = await response.Content.ReadAsAsync<IEnumerable<MovieReview.Models.MovieListing>>();
                        foreach (var listing in listings)
                        {
                            Console.WriteLine(listing.MovieName + "\t " + listing.Rating + "\t " + listing.ReleaseDate + "\t " + listing.Review + "\t " + listing.Reviewer);
                        }
                    }
                    else
                    {
                        Console.WriteLine(response.StatusCode + " " + response.ReasonPhrase);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        //Insert test data list to Azure table
        static void insertTestData(List<MovieListing> listings)
        {
            // add list of movielistings
            foreach (MovieListing item in listings)
            {
                AddAsync(item).Wait();
            }
        }

        // kick off
        static void Main(string[] args)
        {

            // Localhost: http://localhost:4700/
            // Live: http://aliciabrowne.cloudapp.net/

            //    // Movie listing
            //    List<MovieListing> listings = new List<MovieListing>()
            //          { 
            //            new MovieListing { MovieName = "The Shawshank Redemption", Rating = 9.2, ReleaseDate = new DateTime(1994, 10, 14), Review = "good movie", Reviewer="Charlie" },
            //            new MovieListing { MovieName = "The Godfather", Rating = 9.0, ReleaseDate = new DateTime(1972, 03, 24), Review = "great movie", Reviewer = "Dave" },
            //            new MovieListing { MovieName = "The Godfather", Rating = 4.0, ReleaseDate = new DateTime(1972, 03, 24), Review = "Bad movie", Reviewer = "Bob" },
            //            new MovieListing { MovieName = "Schindler's List", Rating = 8.9, ReleaseDate = new DateTime(1993, 12, 15), Review = "average movie", Reviewer = "Alice" },
            //            new MovieListing { MovieName = "Pulp Fiction", Rating = 8.7, ReleaseDate = new DateTime(1994, 10, 14), Review = "bad movie", Reviewer = "Charlie" },
            //            new MovieListing { MovieName = "The Dark Knight", Rating = 8.9, ReleaseDate = new DateTime(2008, 07, 18), Review = "bad movie", Reviewer = "Bob" },
            //            new MovieListing { MovieName = "The Good, the Bad and the Ugly", Rating = 8.9, ReleaseDate = new DateTime(1966, 12, 29), Review = "bad movie", Reviewer = "Alice" },
            //            new MovieListing { MovieName = "12 Angry Men", Rating = 8.9, ReleaseDate = new DateTime(1957, 04, 01), Review = "good movie", Reviewer = "Bob" },
            //            new MovieListing { MovieName = "Fight Club", Rating = 8.8, ReleaseDate = new DateTime(1999, 10, 15), Review = "bad movie", Reviewer = "Dave" },
            //            new MovieListing { MovieName = "Back to the future", Rating = 8.0, ReleaseDate = new DateTime(1985, 07, 05), Review = "average movie", Reviewer = "Dave" },
            //            new MovieListing { MovieName = "Inception", Rating = 8.7, ReleaseDate = new DateTime(2010, 07, 16), Review = "great movie", Reviewer = "Bob" },
            //            new MovieListing { MovieName = "The Departed", Rating = 7.9, ReleaseDate = new DateTime(2006, 10, 06), Review = "excellent movie", Reviewer = "Alice" },
            //            new MovieListing { MovieName = "Django Unchained", Rating = 8.0, ReleaseDate = new DateTime(2012, 12, 25), Review = "bad movie", Reviewer = "Charlie" }
            //            };
            //    insertTestData(listings);

            //Console.WriteLine("GET:");
            //RunAsync().Wait();
            //Console.WriteLine();

            Console.WriteLine("DELETE:");
            DeleteAsync("The Godfather", "Alice").Wait();
            RunAsync().Wait();
            Console.WriteLine();

            Console.WriteLine("ADD:");
            MovieListing newListing = new MovieListing() { MovieName = "The Godfather", Rating = 5.7, ReleaseDate = new DateTime(1972, 03, 24), Review = "Testing..", Reviewer = "Alice" };
            AddAsync(newListing).Wait();
            RunAsync().Wait();
            Console.WriteLine();

            Console.WriteLine("UPDATE:");
            MovieListing updateListing = new MovieListing() { MovieName = "Inception", Rating = 9.5, ReleaseDate = new DateTime(2010, 07, 16), Review = "Average movie", Reviewer = "Dave" };
            UpdateAsync(updateListing).Wait();
            RunAsync().Wait();
            Console.WriteLine();

            //Console.WriteLine("GET BY RATING:");
            //GetByRatingAsync(9.0).Wait();
            //Console.WriteLine();

            //Console.WriteLine("GET BY NAME:");
            //GetByNameAsync("Fight Club").Wait();
            //Console.WriteLine();

            //Console.WriteLine("GET BY RELEASE DATE:");
            //GetByReleaseDateAsync(new DateTime(2008, 07, 01)).Wait();
            //Console.WriteLine();

            //Console.WriteLine("GET BY USER:");
            //GetByUserAsync("Alice").Wait();
            //Console.WriteLine();
        }
    }
}
